import os
import re
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional
from app.config.paths import SMT1_LASER_BASE, SMT2_LASER_BASE


class LaserUtils:
    @staticmethod
    def parse_serial_number(serial_number: str) -> Optional[datetime]:
        """解析流水号中的日期信息
        支持两种格式：
        1) 纯数字月份在前的老格式：例如 S070329900093
           - 正则: S(\d{1,2})(\d{2})(\d{4})(\d{4})
           - 提取: month=第1组, day=第2组
        2) 字母月份的新格式：例如 SA120501738 / SB120501738 / SC120501738
           - 含义: A/B/C 分别表示 10/11/12 月
           - 解析: 字母后的两位数字为日
        """
        if not serial_number or not isinstance(serial_number, str):
            return None

        s = serial_number.strip()

        # 1) 老格式：S + 月(1-2位) + 日(2位) + 4位 + 4位
        m1 = re.match(r'^[sS](\d{1,2})(\d{2})(\d{4})(\d{4})$', s)
        if m1:
            month, day, _, _ = m1.groups()
            month, day = int(month), int(day)
            year = 2025  # 根据实际情况调整
            try:
                if 1 <= month <= 12 and 1 <= day <= 31:
                    return datetime(year, month, day)
            except ValueError:
                return None
            return None

        # 2) 新格式：S + [A-C] + 日(2位) + 其他
        #    A/B/C -> 10/11/12 月；字母后的两位数字作为“日”
        m2 = re.match(r'^[sS]([a-cA-C])(\d{2})', s)
        if m2:
            letter, day = m2.groups()
            letter = letter.upper()
            month_map = {'A': 10, 'B': 11, 'C': 12}
            month = month_map.get(letter)
            day = int(day)
            year = 2025  # 根据实际情况调整
            try:
                if 1 <= day <= 31:
                    return datetime(year, month, day)
            except ValueError:
                return None
            return None

        # 未匹配任何已知格式
        return None

    @staticmethod
    def get_smt1_log_paths(serial_number: str, days_range: List[int] = None) -> List[str]:
        """获取SMT1可能包含该流水号的日志文件路径"""
        if days_range is None:
            days_range = [-1, 0, 1]

        date_time = LaserUtils.parse_serial_number(serial_number)
        if not date_time:
            return []

        file_paths = []
        for day_offset in days_range:
            search_date = date_time + timedelta(days=day_offset)
            file_date = search_date.strftime("%Y%m%d")
            file_path = os.path.join(SMT1_LASER_BASE, f"{file_date}.txt")

            if os.path.exists(file_path) and file_path not in file_paths:
                file_paths.append(file_path)

        return file_paths

    @staticmethod
    def get_smt2_log_paths(serial_number: str, days_range: List[int] = None) -> List[str]:
        """获取SMT2可能包含该流水号的日志文件路径"""
        if days_range is None:
            days_range = [-1, 0, 1]

        date_time = LaserUtils.parse_serial_number(serial_number)
        if not date_time:
            return []

        file_paths = []
        for day_offset in days_range:
            search_date = date_time + timedelta(days=day_offset)
            year = search_date.year
            year_month = search_date.strftime("%Y%m")
            file_date = search_date.strftime("%Y%m%d")
            file_path = os.path.join(SMT2_LASER_BASE, str(year), year_month, f"{file_date}.txt")

            if os.path.exists(file_path) and file_path not in file_paths:
                file_paths.append(file_path)

        return file_paths

    @staticmethod
    def find_record(file_path: str, serial_number: str) -> Optional[str]:
        """在文件中查找记录"""
        if not file_path or not os.path.exists(file_path):
            return None

        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                for line in f:
                    if serial_number in line:
                        return line.strip()
        except Exception as e:
            print(f"读取文件时出错: {e}")
        return None

    @staticmethod
    def extract_product_info(record: str) -> Optional[Dict[str, Any]]:
        """从记录中提取产品信息"""
        if not record:
            return None

        parts = record.split()
        if len(parts) < 5:
            return None

        datetime_str = f"{parts[0]} {parts[1]}"
        product_part = parts[2].strip()
        board_side = parts[3].strip() if len(parts) >= 4 else "未知"

        # 匹配产品代码
        match = re.match(r'(Y\d+-\d+-\d+(?:-[A-Z])?)(?:-(?:BOT|TOP|B0T|T0P|B|T).*)?$', product_part)
        if match:
            short_code = match.group(1)
            return {
                "full_product_code": product_part,
                "short_product_code": short_code,
                "board_side": board_side,
                "laser_time": datetime_str
            }
        return None
